function Myvue(options={})
{
    this.$options=options;
    var data=this._data=this.$options.data;
    //把所有data中的属性用object.defineProperty()方法劫持
    observer (data);
    //数据代理 把data中的数据绑定到Myvue实例上
    for(let  key in data)
    {
        Object.defineProperty(this,key,{
            enumerable:true,
            get()
            {
                return this._data[key];
            },
            set(newval)
            {
                this._data[key]=newval;
            }
        })
    }
    //complier 遍历dom节点 并且替换掉dom中的vm数据7
    initComputed.call(this);
    //
    complier(options.el,this);
    //
    
}
//
function observer(data)
{
    for (let key in data)
    {
        let dep=new Dep();
       let val=data[key];
       if(val!=null&&typeof val ==="object")
       {
         observer(val);
       }
        Object.defineProperty(data,key,{
            enumerable:true,
            get()
            {
                Dep.target&&dep.addsub(Dep.target);
                return val;
            },
            set(newval)
            {
                if(newval===val)
                {
                    return;
                }
                val=newval;
              if(val!=null&&typeof val==="object")
                {
                    observer(val);
                    
                }
                dep.notify();
            }
        })
    }
}
//
function complier(el,vm)
{
  
    vm.$el=document.querySelector(el);
    var fragment=document.createDocumentFragment();
    while(child=vm.$el.firstChild)
    {
        fragment.appendChild(child);
    }
  
    replace(fragment);
    function replace(fragment)
    {
        Array.from(fragment.childNodes).forEach(function (node){
            var text=node.textContent;
            var reg=/\{\{(.*)\}\}/;
            if(node.nodeType==3&&reg.test(text))
            {
               // console.log(RegExp.$1)
                let arr=RegExp.$1.split(".");
                let  val=vm;
               // console.log(val)
                arr.forEach(function(key){
                    val=val[key];
                })
                new Watcher(vm,RegExp.$1,function(newval){
                    node.textContent=text.replace(/\{\{(.*)\}\}/,newval);
                })
                node.textContent=text.replace(/\{\{(.*)\}\}/,val);
            }
            //
            if(node.nodeType===1)
            {
                var attributes=node.attributes;
                Array.from(attributes).forEach(function(attr){
                    let name=attr.name;
                    let value=attr.value;
                    if(name.indexOf("v-")===0)
                    {
                        node.value=vm[value];
                    }
                    //订阅
                    new Watcher(vm,value,function(newval)
                    {
                        node.value=newval;
                    })
                    node.addEventListener("input",function(e){
                        var val=e.target.value;
                        vm[value]=val;
                    })
                })
            }
            if(node.childNodes)
            {
                replace(node);
            }
        })
    }
    vm.$el.appendChild(fragment);
}
//发布订阅这模式
function Dep()
{
    this.subs=[];
    
}
Dep.prototype={
    addsub:function(watcher)
    {
        this.subs.push(watcher);
    },
    notify:function()
    {
        this.subs.forEach(function(watcher)
        {
            watcher.update();
        })
    }
}
function Watcher(vm,exp,fn){
    this.fn=fn;
    this.vm=vm;
    this.exp=exp;
    Dep.target=this;
    let val=vm;
    let arr=exp.split(".");
    arr.forEach(function(k)
    {
        val=val[k];
    })
    Dep.target=null;
};
Watcher.prototype={
    update:function()
    {
        var val=this.vm;
        var exp=this.exp;
        let arr=exp.split(".");
        arr.forEach(function(k)
        {
            val=val[k];
        })
        this.fn(val);
    }
}
//computed属性的实现
function initComputed()
{
    let vm=this;
    let computed=this.$options.computed;
    Object.keys(computed).forEach(function(k)
    {
        Object.defineProperty(vm,k,{
            get:typeof computed[k] ==="function"?computed[k]:computed[k].get
        })
    })
}